<?php

/**
 * User: Administrator
 * Time: 2015/11/3 18:45
 */
class http {


	private $url;
	private $host;
	private $uri;
	private $port;
	private $cookie;
	private $ip;
	private $sock;

	//响应头
	private $ResponseHead;
	//响应内容
	private $ResponseContent;
	//状态码
	private $statusCode;


	public function __construct($url) {
		$this->url = $url;
		$this->parse_url();
		$this->connection();


	}

	/**
	 * 设置cookie
	 * @param $cookie
	 * @return $this
	 */
	public function setCookie($cookie) {
		$this->cookie = $cookie;
		return $this;
	}


	/**
	 * post请求页面
	 * @param $data
	 */
	public function post($data = array()) {
		//获取post请求头
		$request = $this->postRequestHead($data);
		//发送请求数据
		$this->send($request);
		//解析响应内容
		$this->parseResponseContent();
		//返回数据
		return $this->ResponseContent;
	}

	/**
	 * get请求页面
	 */
	public function get() {
		//获取get请求头
		$request = $this->GetRequestHead();
		//发送请求数据
		$this->send($request);
		//解析响应内容
		$this->parseResponseContent();
		//返回数据
		return $this->ResponseContent;
	}

	/**
	 * 上传文件表单
	 * @param array $data
	 * @param       $file
	 * @return mixed
	 */
	public function upload($data = array(), $file) {
		//获取upload请求头
		$request = $this->uploadRequestHead($data, $file);
		//发送请求数据
		$this->send($request);
		//解析响应内容
		$this->parseResponseContent();
		//返回数据
		return $this->ResponseContent;
	}


	/**
	 * 解析响应内容
	 */
	private function parseResponseContent() {
		$head = '';
		//获取响应头
		while (($str = socket_read($this->sock, 1)) !== false) {
			$head .= $str;
			if (strrpos($head, "\r\n\r\n") > 0) {
				break;
			}
		}
		$this->ResponseHead = $head;

		//解析状态码
		$this->parseStatusCode($this->ResponseHead);
		echo "返回状态码：" . $this->statusCode . PHP_EOL;
		//获取响应内容
		switch ($this->statusCode) {
			case "200":
				while ($tmp = socket_read($this->sock, 1000)) {
					$this->ResponseContent .= $tmp;
				}
				break;
			case "301":
			case "302":
				$location = substr($this->ResponseHead, strpos($this->ResponseHead, "Location: "));
				$location = trim(ltrim($location, "Location: "));
				echo "页面重定向: " . $location . PHP_EOL;
				$http                  = new http($location);
				$this->ResponseContent = $http->get();
				break;
			case "304":
				$this->ResponseContent = "304 页面未修改";
				break;
			case "403":
				$this->ResponseContent = "403 服务器拒绝请求";
				break;
			case "404":
				$this->ResponseContent = "404 服务器找不到请求的网页";
				break;
			case "500":
				$this->ResponseContent = "500 服务器内部错误";
				break;
			case "502":
				$this->ResponseContent = "502 网关错误";
				break;
			case "503 ":
				$this->ResponseContent = "503 服务器暂时无法使用";
				break;
			default:
				$this->ResponseContent = "服务器返回一个未知的错误 " . $this->statusCode;
		}
	}


	/**
	 * 解析状态码
	 * @param $ResponseHead
	 */
	private function parseStatusCode($ResponseHead) {
		$tmp              = substr($ResponseHead, 0, strpos($ResponseHead, "\r\n"));
		$code             = substr($tmp, strpos($tmp, " "), 4);
		$this->statusCode = trim($code);
	}


	/**
	 * 通用请求head
	 * @return array
	 */
	private function getCommonHead() {
		return array(
			"Host: " . $this->host,
			"Accept: */*",
			"Accept-Language: zh-cn",
			"Connection: Close",
			"Cookie: " . $this->cookie
		);
	}

	/**
	 * 返回get请求head
	 * @return array|string
	 */
	private function GetRequestHead() {
		$out = array(
			"GET " . $this->uri . " HTTP/1.0",
		);
		$out = array_merge($out, $this->getCommonHead());
		$out = implode("\r\n", $out);
		$out .= "\r\n\r\n";
		return $out;
	}

	/**
	 * 返回post请求head
	 * @param $data
	 * @return array|string
	 */
	private function PostRequestHead($data) {
		$data = http_build_query($data);
		$out  = array(
			"POST " . $this->uri . " HTTP/1.1",
			"Content-Type: application/x-www-form-urlencoded; charset=UTF-8",
			"Content-Length: " . strlen($data),
		);
		$out  = array_merge($out, $this->getCommonHead());
		$out  = implode("\r\n", $out);
		$out .= "\r\n\r\n";
		$out .= $data;
		return $out;
	}

	/**
	 * 上传请求head
	 * @param $data
	 * @param $file
	 * @return array|string
	 */
	private function uploadRequestHead($data, $file) {
		$split           = substr(md5(rand(0, 10000)), 0, 10);
		$request_content = array();
		//请求数据
		if ($data) {
			foreach ($data as $key => $v) {
				$request_content[] = "--" . $split;
				$request_content[] = "Content-Disposition: form-data; name=\"" . $key . "\"" . "\r\n";
				$request_content[] = $v;
			}
		}
		if ($file) {
			foreach ($file as $key => $v) {
				if (!file_exists($v)) {
					continue;
				}
				$file_content      = file_get_contents($v);
				$request_content[] = "--" . $split;
				$request_content[] = "Content-Disposition: form-data; name=\"" . $key . "\"; filename=\"" . basename($v) . "\"";
				$request_content[] = "Content-Type: " . mime_content_type($v) . "\r\n";
				$request_content[] = $file_content;
			}
		}
		$request_content = implode("\r\n", $request_content);
		$request_content .= "\r\n";
		$request_content .= "--" . $split . "--\r\n";

		//请求头
		$request_head = array(
			"POST " . $this->uri . " HTTP/1.1",
			"Content-Type: multipart/form-data; boundary={$split}",
			"Content-Length: " . strlen($request_content)
		);

		$out = array_merge($request_head, $this->getCommonHead());
		$out = implode("\r\n", $out);
		$out .= "\r\n\r\n";
		$out .= $request_content;
		return $out;
	}

	/**
	 * 解析url
	 */
	private function parse_url() {
		$matches    = parse_url($this->url);
		$this->host = $matches['host'];
		@$this->uri = $matches['path'] ? $matches['path'] . '?' . $matches['query'] . $matches['fragment'] : '/';
		$this->port = !empty($matches['port']) ? $matches['port'] : 80;
		$this->ip   = gethostbyname($this->host);

	}

	/**
	 * TCP连接
	 */
	private function connection() {
		$this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
		if ($this->sock < 0) {
			echo "socket_create() failed，Reason:" . socket_strerror($this->sock) . PHP_EOL;
		}

		echo "尝试连接 " . $this->ip . " 端口 " . $this->port . "..." . PHP_EOL;
		$result = socket_connect($this->sock, $this->ip, $this->port);
		if ($result < 0) {
			echo "socket_connect() failed，Reason: ($result) " . socket_strerror($result) . "\n";
		};
	}

	/**
	 * 发送数据
	 * @param $message
	 */
	private function send($message) {
		$res = socket_write($this->sock, $message, strlen($message));
		if (!$res) {
			echo "socket_write() failed: reason: " . socket_strerror($this->sock) . PHP_EOL;
		} else {
			echo '发送http协议成功' . PHP_EOL;
		}
	}

}

//get方式
//$jd= new http("http://order.jd.com/center/list.action");
//$response = $jd->get();
//echo $response;

//post方式
//$topic = new http("http://wl.cloud.com/Home/GroupThread/postThreadAction/groupId/190/threadId/323");
//$cookie = "test";
//$data = array(
//	"content"=>"<p>我也是醉了</p>",
//);
//$response = $topic->setCookie($cookie)->post($data);
//echo $response;

//上传文件
$upload   = new http("http://www.rouruan.com/registration/add");
$cookie   = "";
$response = $upload->upload([
	'username'  => '哈哈哈',
	'contact'   => '18311225569',
	'weixin'    => 'tuyeye',
	'specialty' => '111111',
	'sub'       => '',
], [
	'upfile' => "./vld.php",
	'upfile1' => "./vld.php",
	'upfile2' => "./vld.php"
]);
echo $response;




